/**
 * Copyright 2008 Benjamin Possolo
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.javenue.util.process;

/**
 * A helper interface for managing individual and groups of <tt>Process</tt>es.
 * <p>
 * A <tt>ProcessManager</tt> should be backed by some sort of mechanism that allows
 * <tt>Process</tt>es to be executed in an asynchronous fashion. An implementation
 * may be backed by a <tt>ThreadPoolExecutor</tt> (the default provided implementation),
 * a <tt>WorkManager</tt> (from the commonj specification) or some message-driven
 * system.
 * 
 * @author Benjamin Possolo
 * <p>Created on Jul 24, 2007
 */
public interface ProcessManager {
	
	/**
	 * Disallows any new <tt>Process</tt> instances from being executed.
	 * <p>
	 * <tt>Process</tt>es that are currently running are unaffected. 
	 */
	void disableStartingOfAllProcesses();
	
	/**
	 * Allows new <tt>Process</tt> instances to being executed.
	 * <p>
	 * If starting of processes was already enabled, then this method does nothing.
	 */
	void enableStartingOfAllProcesses();
	
	/**
	 * Disallows any new <tt>Process</tt> instances with a particular process group 
	 * from being executed.
	 * <p>
	 * <tt>Process</tt>es that are currently running are unaffected. 
	 * 
	 * @param processGroup the name of the process group
	 */
	void disableStartingOfProcessesInGroup(String processGroup);
	
	/**
	 * Allows new <tt>Process</tt> instances with a particular process group to being executed.
	 * <p>
	 * If starting of processes with that process group was already enabled,
	 * then this method does nothing.
	 * 
	 * @param processGroup the name of the process group
	 */
	void enableStartingOfProcessesInGroup(String processGroup);
	
	/**
	 * Execute's a <tt>Process</tt> in an asynchronous fashion.
	 * <p>
	 * The <tt>Process</tt>'s <code>run()</code> method is invoked.
	 * 
	 * @param process the process to execute
	 */
	void execute(Process<? extends ProcessState> process);
	
	/**
	 * Checks whether all of the processes are <i>not</i> running.
	 * 
	 * @return true if no processes are running, false otherwise
	 */
	boolean allProcessesAreStopped();
	
	/**
	 * Blocking call that waits for a <tt>Process</tt> to finish executing.
	 * <p>
	 * A <tt>Process</tt> finishes executing once its <code>run()</code> method completes.
	 * <p>
	 * If the thread that has invoked this method is interrupted while waiting,
	 * then the call to this method simply returns (possibly before the <tt>Process</tt>
	 * has completed).
	 * 
	 * @param process the <tt>Process</tt> to wait for
	 */
	void waitForProcessToFinish(Process<? extends ProcessState> process);
	
	/**
	 * Interrupts the thread that is executing the process.
	 * 
	 * @param process the process to interrupt
	 */
	void interrupt(Process<? extends ProcessState> process);
	
	/**
	 * Issues a stop request to a process by invoking its stop() method.
	 * Additionally, if the interrupt flag is true, then the thread executing the
	 * process is interrupted.
	 * 
	 * This is simply a convenience method. It is the exact same as invoking process.stop() 
	 * followed by processManager.interrupt(process).
	 * 
	 * @param process the process to stop
	 * @param interrupt true if the thread executing the process should be interrupted, false otherwise
	 */
	void stop(Process<? extends ProcessState> process, boolean interrupt);
	
	/**
	 * Checks whether a process is currently running.
	 * 
	 * @param process the process to check
	 * @return true if the process is running, false otherwise
	 * @throws IllegalArgumentException if the process is null
	 */
	boolean isProcessRunning(Process<? extends ProcessState> process);
	
	/**
	 * Checks whether a set of processes are all running.
	 * 
	 * @param processes the processes to check
	 * @return true if all the processes in the array are running, false otherwise
	 * @throws IllegalArgumentException if the array is null or if any of its elements are null
	 */
	boolean allProcessesAreRunning(Process<? extends ProcessState>[] processes);
	
	/**
	 * Checks whether any of the processes are running.
	 * 
	 * @param processes the processes to check
	 * @return true if any of the processes in the array is running, false otherwise
	 * @throws IllegalArgumentException if the array is null or if any of its elements are null
	 */
	boolean isAnyProcessRunning(Process<? extends ProcessState>[] processes);
	
	/**
	 * Checks whether any processes in <code>processGroup</code> are running.
	 * 
	 * @param processGroup the name of the process group
	 * @return true if any processes in <code>processGroup</code> are running,
	 * false otherwise
	 */
	boolean isAnyProcessRunning(String processGroup);
	
	/**
	 * Checks whether all of the processes are <i>not</i> running.
	 * 
	 * @param processes the processes to check
	 * @return true if all of the processes in the array are <i>not</i> running (i.e. stopped),
	 * false otherwise
	 * @throws IllegalArgumentException if the array is null or if any of its elements are null
	 */
	boolean allProcessesAreStopped(Process<? extends ProcessState>[] processes);
	
	/**
	 * Checks whether all process belonging to the <code>processGroup</code>
	 * are <i>not</i> running.
	 * 
	 * @param processGroup the name of the process group
	 * @return true if all of the processes with the specified 
	 * <code>processGroup</code> are <i>not</i> running (i.e. stopped),
	 * false otherwise
	 */
	boolean allProcessesAreStopped(String processGroup);
	
}
